HmJS.$Import('core.element');

/*
---
name: FitImage
version: 0.1.1-0
description: fix in place and fitto screen any background image
license: MIT-style license.
download: http://mootools.net/forge/p/fitimage
source: http://github.com/kpobococ/FitImage/

authors:
- Anton Suprun

requires:
- Core/Array
- Core/Class.Extras
- Core/DOMReady
- Core/Element.Dimensions
provides: [FitImage]
...
*/

/*
How to use
----------

Using FitImage is as simple as it gets:

    #JS
    new FitImage('/background.jpg');

Also note, that this plugin does not include any style properties except those
that are dynamically generated, so you will have to add some styles to your
stylesheets:

    #CSS
    img.resize-background {
        position: fixed;
        z-index: 1;
    }

Also, you want to create a wrapper for your content and set its z-index to keep
it above the image:

    #CSS
    div.global-wrapper {
        position: relative;
        z-index: 2;
    }

Configuration
-------------

The following configuration options are available:

* `class`: image element class name(s)
* `center`: should the image be centered or not. Defaults to `true`.
* `minWidth`: minimum image width. If the screen width is less than the minimum width, image size will not be reduced. Defaults to `1024`.
* `minHeight`: minimum image height. Behaves identical to `minWidth`. Defaults to `768`.
* `primary`: defines which dimension should perfectly fit the screen. Either `width`, `height` or `auto`. The `auto` setting makes sure the image completely covers the screen. Defaults to `auto`.
* `injectElement`: element to be passed to the inject method. Defaults to `document.body`.
* `injectPosition`: position to be passed to the inject method. Defaults to `top`.

Image resizing operations always keep the image proportions intact.

Examples
--------

A background image aligned on the left side and fixed to fit screen height:

    #JS
    new FitImage('/background.jpg', {
        'center': false,
        'primary': 'height'
    });

And styles:

    #CSS
    img.resize-background {
        position: fixed;
        z-index: 1;
        top: 0;
        right: 0;
    }
    .wrapper-global {
        min-height: 100%;
        position: relative;
        z-index: 2;
    }
*/

HmJS.register('util.dom.FitImage', function ($ns) {

	return new Class({

		Implements: [Events, Options],

		options: {
			'class': 'resize-background',
			'center': true,
			'minWidth': 1024,
			'minHeight': 768,
			'primary': 'auto',
			'injectElement': null,
			'injectPosition': 'top'
		},

		initialize: function (image, options) {
			options = options || {};
			options.primary = options.primary && ['width', 'height', 'auto'].contains(options.primary)
			? options.primary
			: 'auto';
			this.setOptions(options);
			// *** Permanently bind some methods
			this.resize = this.resize.bind(this);
			this.inject = this.inject.bind(this);
			// *** Load the image
			this.image = new Element('img', {
				'src': image,
				'class': this.options['class']
			}).addEvent('load', this.inject);
			// In case browser does not support load event for images
			this.attach();
		},

		attach: function () {
			window.addEvents({
				'load': this.inject,
				'domready': this.resize,
				'resize': this.resize
			});
		},

		detach: function () {
			window.removeEvents({
				'load': this.inject,
				'domready': this.resize,
				'resize': this.resize
			});
		},

		inject: function () {
			if (!this.injected) {
				if (!this.options.injectElement) {
					this.options.injectElement = document.body;
				}
				this.image.inject(this.options.injectElement, this.options.injectPosition);
				this.injected = true;
			}
			// *** If image fails to resize, return launching resize on inject call even after inject becomes true
			this.resize();
			return this;
		},

		resize: function () {
			var size = window.getSize(),
					rate = size.x / size.y,
					styles = {};

			if (!this.size || this.size.x == 0) {
				// *** Detect image size
				this.size = this.image.getSize();
				if (this.size.x == 0) { return this; } // Not loaded yet
				this.rate = this.size.x / this.size.y;
			}

			// *** Set first dimension size
			if (this.options.primary == 'width' || (this.options.primary == 'auto' && this.rate < rate)) {
				styles.width = size.x;
				styles.height = null;
			} else if (this.options.primary == 'height' || (this.options.primary == 'auto' && this.rate > rate)) {
				styles.width = null;
				styles.height = size.y;
			} else {
				// *** Perfect fit!
				styles.width = size.x;
				styles.height = size.y;
			}

			// *** Min width && height
			if (styles.width !== null && this.options.minWidth > styles.width) {
				styles.width = this.options.minWidth;
			}
			if (styles.height !== null && this.options.minHeight > styles.height) {
				styles.height = this.options.minHeight;
			}

			// *** Calculate second dimension size
			if (styles.width === null) {
				styles.width = Math.round(styles.height * this.size.x / this.size.y);
			}
			if (styles.height === null) {
				styles.height = Math.round(styles.width * this.size.y / this.size.x);
			}

			// *** Position in the center of the screen
			if (this.options.center) {
				// *** Horizontal
				if (styles.width > size.x) {
					styles.left = 0 - Math.round((styles.width - size.x) / 2);
				} else if (styles.width < size.x) {
					styles.left = Math.round((size.x - styles.width) / 2);
				} else {
					styles.left = 0;
				}

				// *** Vertical
				if (styles.height > size.y) {
					styles.top = 0 - Math.round((styles.height - size.y) / 2);
				} else if (styles.height < size.y) {
					styles.top = Math.round((size.y - styles.height) / 2);
				} else {
					styles.top = 0;
				}
			}

			this.image.setStyles(styles);
			return this;
		},

		toElement: function () {
			return this.image;
		}

	});

});